﻿#include "log.h"
#include <stdarg.h>
static LogProfile* sLogProfile = NULL;
int	_logInit() {
	if (NULL != sLogProfile) {
		return -1;
	}
	sLogProfile = (LogProfile*)malloc(sizeof(LogProfile));
	memset(sLogProfile, 0x00, sizeof(LogProfile));
	sLogProfile->bPrintFileNameLine = 1;
	sLogProfile->bPrintLevel = TLogMsg;
	sLogProfile->VaildMinUTC = 1577808000;
	return 0;
}
int	_logSetProfile(LogProfile* Profile) {
	if (sLogProfile == NULL) {
		return -1;
	}
	else {
		*sLogProfile = *Profile;
		return 0;
	}
}
LogProfile* _logGetProfile() {
	return sLogProfile;
}


static void _PrintIteam(LogItem* _Iteam)
{
	struct tm _tm = { 0 };
	time_t _t = _Iteam->Timeval_tvSec;
	AvLocalTimeS(&_t, &_tm);
	char timePrintstr[128] = { 0 };
	char fileNameLine[LOG_MAX_FILENAME_LENGTH + 4 + 4] = { 0 };
	if (_tm.tm_year > (2019 - 1970)) {
		sprintf(timePrintstr, "%04d%02d%02d %02d:%02d:%02d.%03d|", _tm.tm_year + 1900, _tm.tm_mon + 1, _tm.tm_mday,
			_tm.tm_hour, _tm.tm_min, _tm.tm_sec, (int)(_Iteam->Timeval_tvUsec / 1000));
	}
	else {
		sprintf(timePrintstr, "%012.3f|", (double)((double)_Iteam->UpTime / 1000));
	}

	if (sLogProfile->bPrintFileNameLine == 1) {
		int FileNameLength = strlen(_Iteam->FileName);
		if (FileNameLength < (LOG_MAX_FILENAME_LENGTH - 1)) {
			int lengPrev = (LOG_MAX_FILENAME_LENGTH - 1) - FileNameLength;
			memset(fileNameLine, ' ', lengPrev);
			strcpy(&fileNameLine[lengPrev], _Iteam->FileName);
		}
		else {
			strncpy(fileNameLine, _Iteam->FileName, LOG_MAX_FILENAME_LENGTH - 1);
		}
		fileNameLine[LOG_MAX_FILENAME_LENGTH - 1] = '\0';
		sprintf(fileNameLine, "%s:%04d|  ", fileNameLine, _Iteam->FileLine);
	}
	else {
		sprintf(fileNameLine, "%s", "  ");
	}
	switch (_Iteam->Type)
	{
	case TLogMsg:
#if defined(WIN32)
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 10);
		printf("%s%s%s", timePrintstr, fileNameLine, _Iteam->Msg);
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
#elif defined(__ANDROID__)
		__android_log_print(ANDROID_LOG_INFO, LOG_TAG, "\033[1;32m %s", _Iteam->Msg);
#else
		printf("\033[1;32m%s%s%s\033[m", timePrintstr, fileNameLine, _Iteam->Msg);
#endif
		break;
	case TLogWarn:
#if defined(WIN32)
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
		printf("%s%s%s", timePrintstr, fileNameLine, _Iteam->Msg);
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
#elif defined(__ANDROID__)
		__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "\033[1;33m %s", _Iteam->Msg);
#else
		printf("\033[1;33m%s%s%s\033[m", timePrintstr, fileNameLine, _Iteam->Msg);
#endif
		break;
	case TLogHint:
	case TLogError:
#if defined(WIN32)
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 12);
		printf("%s%s%s", timePrintstr, fileNameLine, _Iteam->Msg);
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 15);
#elif defined(__ANDROID__)
		__android_log_print(ANDROID_LOG_WARN, LOG_TAG, "\033[0;31m %s", _Iteam->Msg);
#else
		printf("\033[0;31m%s%s%s\033[m", timePrintstr, fileNameLine, _Iteam->Msg);
#endif
		break;

	default:
		break;
	}
}


void _DLogMsg(char* File, int Line, const char* fmt, ...)
{
	LogItem Item = { 0 };
	int nSize = 0;
	Item.Type = TLogMsg;
	{//变参
		va_list ap;
		va_start(ap, fmt);
		nSize += vsnprintf(Item.Msg + nSize, LOG_MAX_BUFFER - 1 - nSize, fmt, ap);
		va_end(ap);
	}
	{//位置
		strncpy(Item.FileName, File, LOG_MAX_FILENAME_LENGTH - 1);
		Item.FileLine = Line;
	}
	{//时间
		AppRunMSec(Item.UpTime);
		struct timeval tv;
		AvGetTimeOfDay(&tv, NULL);
		if (tv.tv_sec > sLogProfile->VaildMinUTC) {
			Item.Timeval_tvSec = tv.tv_sec;
			Item.Timeval_tvUsec = tv.tv_usec;
		}
	}
	if (sLogProfile->bPrintLevel <= Item.Type) {
		_PrintIteam(&Item);
	}
	if (NULL != sLogProfile->LogProc) {
		sLogProfile->LogProc(&Item);
	}
}
void _DLogErr(char* File, int Line, const char* fmt, ...)
{
	LogItem Item = { 0 };
	int nSize = 0;
	Item.Type = TLogError;
	{//变参
		va_list ap;
		va_start(ap, fmt);
		nSize += vsnprintf(Item.Msg + nSize, LOG_MAX_BUFFER - 1 - nSize, fmt, ap);
		va_end(ap);
	}
	{//位置
		strncpy(Item.FileName, File, LOG_MAX_FILENAME_LENGTH - 1);
		Item.FileLine = Line;
	}
	{//时间
		AppRunMSec(Item.UpTime);
		struct timeval tv;
		AvGetTimeOfDay(&tv, NULL);
		if (tv.tv_sec > sLogProfile->VaildMinUTC) {
			Item.Timeval_tvSec = tv.tv_sec;
			Item.Timeval_tvUsec = tv.tv_usec;
		}
	}
	if (sLogProfile->bPrintLevel <= Item.Type) {
		_PrintIteam(&Item);
	}
	if (NULL != sLogProfile->LogProc) {
		sLogProfile->LogProc(&Item);
	}
}
void _DLogWarn(char* File, int Line, const char* fmt, ...)
{
	LogItem Item = { 0 };
	int nSize = 0;
	Item.Type = TLogWarn;
	{//变参
		va_list ap;
		va_start(ap, fmt);
		nSize += vsnprintf(Item.Msg + nSize, LOG_MAX_BUFFER - 1 - nSize, fmt, ap);
		va_end(ap);
	}
	{//位置
		strncpy(Item.FileName, File, LOG_MAX_FILENAME_LENGTH - 1);
		Item.FileLine = Line;
	}
	{//时间
		AppRunMSec(Item.UpTime);
		struct timeval tv;
		AvGetTimeOfDay(&tv, NULL);
		if (tv.tv_sec > sLogProfile->VaildMinUTC) {
			Item.Timeval_tvSec = tv.tv_sec;
			Item.Timeval_tvUsec = tv.tv_usec;
		}
	}
	if (sLogProfile->bPrintLevel <= Item.Type) {
		_PrintIteam(&Item);
	}
	if (NULL != sLogProfile->LogProc) {
		sLogProfile->LogProc(&Item);
	}
}

void _DLogHint(char* File, int Line, const char* fmt, ...)
{
	LogItem Item = { 0 };
	int nSize = 0;
	Item.Type = TLogHint;
	{//变参
		va_list ap;
		va_start(ap, fmt);
		nSize += vsnprintf(Item.Msg + nSize, LOG_MAX_BUFFER - 1 - nSize, fmt, ap);
		va_end(ap);
	}
	{//位置
		strncpy(Item.FileName, File, LOG_MAX_FILENAME_LENGTH - 1);
		Item.FileLine = Line;
	}
	{//时间
		AppRunMSec(Item.UpTime);
		struct timeval tv;
		AvGetTimeOfDay(&tv, NULL);
		if (tv.tv_sec > sLogProfile->VaildMinUTC) {
			Item.Timeval_tvSec = tv.tv_sec;
			Item.Timeval_tvUsec = tv.tv_usec;
		}
	}
	if (sLogProfile->bPrintLevel <= Item.Type) {
		_PrintIteam(&Item);
	}
	if (NULL != sLogProfile->LogProc) {
		sLogProfile->LogProc(&Item);
	}
}
